//
// Created by benxb on 2021/12/21.
//

#ifndef BENXDB_SIMPLE_VALUE_H
#define BENXDB_SIMPLE_VALUE_H

#include <cstdint>
#include <common/config.h>

namespace benxdb {

enum SimpleType : uint32_t {
    STYPE_INVALID = 0,
    STYPE_INTEGER,
    STYPE_BIGINT,
    STYPE_FLOAT,
    STYPE_DECIMAL,
    STYPE_TIMESTAMP,
};

/**
 * SimpleValue only support fixed_length type
 */
class SimpleValue {
public:
    SimpleValue() = default;
    explicit SimpleValue(SimpleType type) : type_(type) {}
    SimpleValue(SimpleType type, const char *data);

    SimpleValue(SimpleType type, int32_t val);
    SimpleValue(SimpleType type, float val);
    SimpleValue(SimpleType type, double val);
    SimpleValue(SimpleType type, int64_t val);
    SimpleValue(SimpleType type, uint64_t val);

    [[nodiscard]] bool CompareEquals(const SimpleValue &o) const;
    [[nodiscard]] bool CompareNotEquals(const SimpleValue &o) const;
    [[nodiscard]] bool CompareLessThan(const SimpleValue &o) const;
    [[nodiscard]] bool CompareLessThanEquals(const SimpleValue &o) const;
    [[nodiscard]] bool CompareGreaterThan(const SimpleValue &o) const;
    [[nodiscard]] bool CompareGreaterThanEquals(const SimpleValue &o) const;

    SimpleValue Add(const SimpleValue &o);
    SimpleValue Subtract(const SimpleValue &o);
    SimpleValue Multiply(const SimpleValue &o);
    SimpleValue Divide(const SimpleValue &o);

    template <class T>
    inline T GetAs() const {
        return *reinterpret_cast<const T *>(&value_);
    }

    SimpleType GetType() { return type_; }

    void SetType(SimpleType type) { type_ = type; }

    char* GetVal() { return reinterpret_cast<char *>(&value_);}

    int GetSize();

    // Serialize this value into the given storage space. The inlined parameter
    // indicates whether we are allowed to inline this value into the storage
    // space, or whether we must store only a reference to this value. If inlined
    // is false, we may use the provided data_ pool to allocate space for this
    // value, storing a reference into the allocated pool space in the storage.
    /**
     * Serialize to storage
     * @param storage
     * @return length
     */
    int SerializeTo(char *storage);

    // Deserialize a value of the given type from the given storage space.
    static SimpleValue DeserializeFrom(const char *storage, SimpleType type);

    static int GetSizeOfType(SimpleType type);

    static SimpleValue GetMinValueOfType(SimpleType type);

    static SimpleValue GetMaxValueOfType(SimpleType type);

    [[nodiscard]] inline bool Compare(CompareSign sign, const SimpleValue &o) const {
        switch (sign) {
            case EQUAL:
                return CompareEquals(o);
            case LESS_THAN:
                return CompareLessThan(o);
            case LESS_EQUAL:
                return CompareLessThanEquals(o);
            case GREATER_THAN:
                return CompareGreaterThan(o);
            case GREATER_EQUAL:
                return CompareGreaterThanEquals(o);
            default:
                return false;
        }
    }

protected:
    // The actual value item
    union Val {
        int32_t integer_;
        int64_t bigint_;
        float float_;
        double decimal_;
        uint64_t timestamp_;
    } value_{};

    SimpleType type_;
};

}

#endif //BENXDB_VALUE_H
